/**
 * 文件名：@AbstractUseDataSourceAdvisor.java <br/>
 * 包名：cn.efunbox.afw.data.datasource <br/>
 * 项目名：afw-data <br/>
 * @author xtwin <br/>
 */
package cn.efunbox.afw.data.datasource.dynamic;

import java.lang.reflect.Method;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.AbstractPointcutAdvisor;

import cn.efunbox.afw.core.holder.StackHolder;

/**
 * 类名：AbstractUseDataSourceAdvisor  <br />
 *
 * 功能：数据源注解Advisor基础实现
 *
 * @author xtwin <br />
 * 创建时间：2016年7月31日 下午3:26:25  <br />
 * @version 2016年7月31日
 */
public abstract class AbstractUseDataSourceAdvisor extends AbstractPointcutAdvisor {
	
	/** add by xtwin 2016年7月31日 下午3:53:15 */
	private static final long serialVersionUID = -3308088208045703723L;
	
	// 数据源持有者
	protected StackHolder<String> dataSourceHolder;

	/**
	 * 功能: <br/>
	 * 
	 * 重写：xtwin <br/>
	 * 
	 * @version ：2016年7月31日 下午3:27:31<br/>
	 * 
	 * @return <br/>
	 * @see org.springframework.aop.Advisor#getAdvice()
	 */
	@Override
	public Advice getAdvice() {
		return new MethodInterceptor() {
			@Override
			public Object invoke(MethodInvocation invocation) throws Throwable {
				// 查找数据源定义
				UseDataSource uds = findAnnotation(invocation.getMethod(), invocation.getThis().getClass());
				
				// 没有找到注解定义，则直接执行返回
				if (null == uds) {
					return invocation.proceed();
				}
				
				// 推入当前的数据源定义
				dataSourceHolder.push(uds.value());
				
				try {
					// 执行目标方法
					return invocation.proceed();
				} finally {
					// 弹出数据源定义，恢复到目标方法执行之前的状态
					dataSourceHolder.pop();
				}
			}
		};
	}
	
	/**
	 * 功能：查找注解定义 <br/>
	 *
	 * @author xtwin <br/>
	 * @version 2016年7月31日 下午3:34:55 <br/>
	 */
	protected abstract UseDataSource findAnnotation(Method method, Class<?> clazz);

	/**
	 * @version 2016年7月31日-下午4:01:22
	 */
	public void setDataSourceHolder(StackHolder<String> dataSourceHolder) {
		this.dataSourceHolder = dataSourceHolder;
	}
}